package com.xzx.groupchat;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

/**
 *
 * @author xinzhixuan
 * @version 1.0
 * @date 2025/11/5 14:40
 */
@Slf4j
public class ChatServerHandler extends SimpleChannelInboundHandler<String> {

    private static DefaultChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("[客户端] - {} 加入群聊", ctx.channel().remoteAddress());
        channelGroup.writeAndFlush("[客户端] - " + ctx.channel().remoteAddress() + " 加入群聊");
        channelGroup.add(ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("[客户端] - {} 离开群聊", ctx.channel().remoteAddress());
        channelGroup.remove(ctx.channel());
        channelGroup.writeAndFlush("[客户端] - " + ctx.channel().remoteAddress() + " 离开群聊");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        log.info("[客户端] - {} 发送消息:{}", ctx.channel().remoteAddress(), msg);
        channelGroup.forEach(channel -> {
            if (channel != ctx.channel()) {
                channel.writeAndFlush("[客户端] - " + ctx.channel().remoteAddress() + " 发送消息:" + msg);
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        log.error("exceptionCaught, channel:{}", ctx.channel().remoteAddress(), cause);
        ctx.close();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
       if (evt instanceof IdleStateEvent) {
           IdleStateEvent event = (IdleStateEvent) evt;
           log.debug("IdleStateEvent:{}", event);
           switch (event.state()) {
               case READER_IDLE:
                   log.info("[客户端] - {} 读超时", ctx.channel().remoteAddress());
                   break;
               case WRITER_IDLE:
                   log.info("[客户端] - {} 写超时", ctx.channel().remoteAddress());
                   break;
               case ALL_IDLE:
                   // 当然这里就可以发送PING消息，来保持心跳，如果长时间没有心跳，需要关闭掉这个channel
                   log.info("[客户端] - {} 写超时", ctx.channel().remoteAddress());
                   ctx.channel().close();
           }
       }
    }
}
